#include "smart-device-gateway.h"
#include <functional>

SmartDeviceGateway::SmartDeviceGateway(const string &uartDevice)
    : udpNetThread(nullptr),
      mqttNetThread(nullptr),
      worker(uartDevice)
{
    // 初始化udp和qt界面交互
    udpNetCommunication = new UdpNetCommunication("192.168.2.236", 8899);

    // 初始化mqtt和服务端通讯
    mqttNetCommunication = new MQTTNetCommunication("192.168.2.236", 1883);
    // 处理管道内的数据的线程
    commnicationHandlerThread = new thread(std::bind(&SmartDeviceGateway::commnicationHandlerRun, this));
}

SmartDeviceGateway::~SmartDeviceGateway()
{
    delete udpNetCommunication;
}

void SmartDeviceGateway::start()
{
    if (!udpNetThread)
    {
        // 创建一个子线程收数据
        udpNetThread = new thread(std::bind(&SmartDeviceGateway::udpNetCommunicationRun, this));
    }

    if (!mqttNetThread)
    {
        mqttNetThread = new thread(std::bind(&SmartDeviceGateway::mqttNetCommunicationRun, this));
    }
}

void SmartDeviceGateway::udpNetCommunicationRun(void)
{
    // 收到的请求放到队列中去 唤醒从队列中请求的线程
    // 队列中的数据,请求包+通讯方式 是udp的数据包还是mqtt的数据包
    while (1)
    {
        // UDP不停的收
        vector<uint8_t> packet;
        bool ok = udpNetCommunication->recvPacket(packet);
        if (!ok)
        {
            break;
        }
        queueMtx.lock();
        messageQueue.push(CommunicationMessage(packet, udpNetCommunication));
        queueMtx.unlock();
        // 唤醒消息处理线程的函数
        notfiy();
    }
}

void SmartDeviceGateway::mqttNetCommunicationRun(void)
{

    // 收到的请求放到队列中去 唤醒从队列中请求的线程
    // 队列中的数据,请求包+通讯方式 是udp的数据包还是mqtt的数据包
    while (1)
    {
        // UDP不停的收
        vector<uint8_t> packet;
        bool ok = mqttNetCommunication->recvPacket(packet);
        if (!ok)
        {
            break;
        }
        queueMtx.lock();
        messageQueue.push(CommunicationMessage(packet, mqttNetCommunication));
        queueMtx.unlock();
        // 唤醒消息处理线程的函数
        notfiy();
    }
}

void SmartDeviceGateway::commnicationHandlerRun(void)
{
    while (1)
    {
        queueMtx.lock();
        bool queueEmpty = messageQueue.empty();
        queueMtx.unlock();
        if (queueEmpty)
        {
            // 线程等待被唤醒
            wait();
        }

        queueMtx.lock();
        CommunicationMessage message = messageQueue.front();
        messageQueue.pop();
        queueMtx.unlock();
        // 对消息进行处理
        worker.dowork(message);
    }
}

void SmartDeviceGateway::wait(void)
{
    std::unique_lock<mutex> lck(mtx);
    cv.wait(lck);
}

void SmartDeviceGateway::notfiy(void)
{
    std::unique_lock<mutex> lck(mtx);
    cv.notify_all();
}
